#coding=utf-8
import struct, md5, time
import Queue
from twisted.internet.protocol import Protocol, ReconnectingClientFactory, ServerFactory, ClientFactory
from twisted.internet import reactor
from twisted.internet.error import ConnectionDone, ConnectionLost
from zope.interface import implements, Interface
from threading import Thread

from EventManager import *
import Utils
try:
    import cStringIO as StringIO
except ImportError:
    import StringIO

from log import log

RESEND_SECOND = 6
ACTIVE_SECOND = 10

GENERIC_NACK = 0x80000000
BIND_RECEIVER = 0x00000001
BIND_RECEIVER_RESP = 0x80000001
BIND_TRANSMITTER = 0x00000002
BIND_TRANSMITTER_RESP = 0x80000002
QUERY_SM = 0x00000003
QUERY_SM_RESP = 0x80000003
SUBMIT_SM = 0x00000004
SUBMIT_SM_RESP = 0x80000004
DELIVER_SM = 0x00000005
DELIVER_SM = 0x80000005
UNBIND = 0x00000006
UNBIND_RESP = 0x80000006
REPLACE_SM = 0x00000007
REPLACE_SM_RESP = 0x80000007
CANCEL_SM = 0x00000008
CANCEL_SM_RESP = 0x80000008
BIND_TRANSCEIVER = 0x00000009
BIND_TRANSCEIVER_RESP = 0x80000009
OUTBIND = 0x0000000B
ENQUIRE_LINK = 0x00000015
ENQUIRE_LINK_RESP = 0x80000015
SUBMIT_MULTI = 0x00000021
SUBMIT_MULTI_RESP = 0x80000021
ALERT_NOTIFICATION = 0x00000102
DATA_SM = 0x00000103
DATA_SM_RESP = 0x80000103
QUERY_USERSTATE = 0x0000000C
QUERY_USERSTATE_RESP = 0x8000000C
#ERROR CODE DEFINE
ESME_ROK
ESME_RINVMSGLEN
ESME_RINVCMDLEN
ESME_RINVCMDID
ESME_RINVBNDSTS
ESME_RALYBND
ESME_RINVPRTFLG
ESME_RINVREGDLVFLG
ESME_RSYSERR
ESME_RINVSRCADR
ESME_RINVDSTADR
ESME_RINVMSGID
ESME_RBINDFAIL
ESME_RINVPASWD
ESME_RINVSYSID
ESME_RCANCELFAIL
ESME_RREPLACEFAIL
ESME_RMSGQFUL
ESME_RINVSERTYP
ESME_RINVNUMDESTS
ESME_RINVDLNAME
ESME_RINVDESTFLAG
ESME_RINVSUBREP
ESME_RINVESMCLASS
ESME_RCNTSUBDL
ESME_RSUBMITFAIL
ESME_RINVSRCTON
ESME_RINVSRCNPI
ESME_RINVDSTTON
ESME_RINVDSTNPI
ESME_RINVSYSTYP
ESME_RINVREPFLAG
ESME_RINVNUMMSGS
ESME_RTHROTTLED
ESME_RINVSCHED
ESME_RINVEXPIRY
ESME_RINVDFTMSGID
ESME_RX_T_APPN
ESME_RX_P_APPN
ESME_RX_R_APPN
ESME_RQUERYFAIL
ESME_RINVOPTPARSTREAM
ESME_ROPTPARNOTALLWD
ESME_RINVPARLEN
ESME_RMISSINGOPTPARAM
ESME_RINVOPTPARAMVAL
ESME_RDELIVERYFAILURE
ESME_RUNKNOWNERR

class SmgpParseError(Exception):
    """The incoming data is not in valid Smgp packet format."""
    pass
class IEncodable(Interface):
    """
    Interface for something which can be encoded to and decoded
    from a file object.
    """
    def encode(strio, compDict = None):
        """
        Write a representation of this object to the given
        file object.

        @type strio: File-like object
        @param strio: The stream to which to write bytes

        @type compDict: C{dict} or C{None}
        @param compDict: A dictionary of backreference addresses that have
        have already been written to this stream and that may be used for
        compression.
        """

    def decode(strio, length = 0):
        """
        Reconstruct an object from data read from the given
        file object.

        @type strio: File-like object
        @param strio: The stream from which bytes may be read

        @type length: C{int} or C{None}
        @param length: The number of bytes in this RDATA field.  Most
        implementations can ignore this value.  Only in the case of
        records similar to TXT where the total length is in no way
        encoded in the data is it necessary.
        """

class SeqGen(object):
    seqID = 0
    @staticmethod
    def nextID():
        SeqGen.seqID = SeqGen.seqID + 1
        return SeqGen.seqID
        
        
class Smgp30Util(object):
    seqID = 0
    maxSeq = 0x999999
    @staticmethod
    def id2str(id):
        if id == LOGIN:
            return 'Smgp_Login'
        elif id == LOGIN_RESP:
            return 'Smgp_Login_Resp'
        elif id == SUBMIT:
            return 'Smgp_Submit'
        elif id == SUBMIT_RESP:
            return 'Smgp_Submit_Resp'
        elif id == DELIVER:
            return 'Smgp_Deliver'
        elif id == DELIVER_RESP:
            return 'Smgp_Deliver_Resp'
        elif id == ACTIVE_TEST:
            return 'Smgp_Active_Test'
        elif id == ACTIVE_TEST_RESP:
            return 'Smgp_Active_Test_Resp'
        elif id == EXIT:
            return 'Smgp_Exit'
        elif id == EXIT_RESP:
            return 'Smgp_Exit_Resp'
        elif id == QUERY:
            return 'Smgp_Query'
        elif id == QUERY_RESP:
            return 'Smgp_Query_Resp'
        elif id == FORWARD:
            return 'Smgp_Forward'
        elif id == FORWARD_RESP:
            return 'Smgp_Forward_Resp'
        elif id == MT_ROUTE_UPDATE:
            return 'Smgp_MT_Route_Update'
        elif id == MT_ROUTE_UPDATE_RESP:
            return 'Smgp_MT_Route_Update_Resp'
        elif id == MO_ROUTE_UPDATE:
            return 'Smgp_MO_Route_Update'
        elif id == MO_ROUTE_UPDATE_RESP:
            return 'Smgp_MO_Route_Update_Resp'
        elif id == PAYMENT_REQUEST:
            return 'Smgp_Payment_Request'
        elif id == PAYMENT_REQUEST_RESP:
            return 'Smgp_Payment_Request_Resp'
        elif id == PAYMENT_AFFIRM:
            return 'Smgp_Payment_Affirm'
        elif id == PAYMENT_AFFIRM_RESP:
            return 'Smgp_Payment_Affirm_Resp'
        elif id == QUERY_USERSTATE:
            return 'Smgp_Userstate'
        elif id == QUERY_USERSTATE_RESP:
            return 'Smgp_Userstate_Resp'  
        else:
            return ''
        
        
    @staticmethod
    def strtobcd(strin):
        bcd = StringIO.StringIO()
        flag = False
        
        for b in str(strin):
            if flag:
                tmp |= int(b) 
                bcd.write(chr(tmp))
                flag = False
            else:                
                tmp = int(b) << 4
                flag = True
            
        return bcd.getvalue()
    
    @staticmethod
    def genTimeStr(t=time.localtime()):
        #t = time.localtime()
        return time.strftime('%m%d%H%M%S', t)
    @staticmethod
    def genRecvTime(t=time.localtime()):
        #t = time.localtime()
        return time.strftime('%Y%m%d%H%M%S', t)
    @staticmethod
    def getSequenceStr():
        Smgp30Util.seqID += 1
        if Smgp30Util.seqID > Smgp30Util.maxSeq:
            Smgp30Util.seqID = 0
        return str(Smgp30Util.seqID)
    
    @staticmethod    
    def genMsgID():
        smgwid='755061'
        timestr=Smgp30Util.genTimeStr()
        seqstr = Smgp30Util.getSequenceStr()
        return Smgp30Util.strtobcd(smgwid + timestr + seqstr)
    
    
#    @staticmethod
#    def auth(m):
#        #验证用户，
#        a = accounts.getAccount(m.clientID.strip('\x00'))
#        if a == None:
#            return False
#        
#        if not a.checkSupportProtocol(SMGP30):
#            return False
#        
#        #ip验证
#        #if 
#        m = md5.new()
#        authIO = StringIO.StringIO()
#        authIO.write(a.username)
#        for i in range(7):
#            authIO.write(chr(0))
#        authIO.write(a.password)
#        #self.timestamp = time.strftime('%m%d%H%M%S', time.localtime())
#        authIO.write(str(m.timestamp).zfill(10))
#        m.update(authIO.getvalue())
#        #if m.a m.digest()


    @staticmethod
    def genTimestampInt(t=time.localtime()):
        return int(time.strftime('%m%d%H%M%S', t))
    @staticmethod
    def genAuth(username = '', password = ''):
        m = md5.new()
        authIO = StringIO.StringIO()
        authIO.write(username)
        authIO.write('\x00' * 7)
        authIO.write(password)
        #self.timestamp = time.strftime('%m%d%H%M%S', time.localtime())
        ts = Smgp30Util.genTimestampInt()
        authIO.write(str(ts).zfill(10))
        m.update(authIO.getvalue())
        return (ts, m.digest())
        #if m.a m.digest()
        
        
    @staticmethod
    def makeLogin(username = '',password = ''):
        m = Smgp30Login()
        m.clientID = username
        #m.authenticatorClient = Smgp30Util.genAuth(username, password)
        (m.timestamp, m.authenticatorClient) = Smgp30Util.genAuth(username, password)
        return m
    
    @staticmethod
    def makeLoginResp(m):
        p = Smgp30LoginResp()
        p.sequenceID = m.sequenceID
        return p
        
    @staticmethod
    def makeSubmit(content='', f=15):
        p = Smgp30Submit() 
        p.destTermID = '13715053570'
        p.destTermIDCount = 1
        #内容的编码是个问题,需要仔细处理
        #在msgFormat为0时,用ACSII,为4时,二进制,为8时,UCS,为15时GBK
        if f == 15:
            p.msgFormat = 0x15
            #TODO:中文编码可以用GB2312 GBK GB18303
            #可以在配置文件中增加编码方案的配置
            p.msgContent = content.encode('GB18030')
            p.msgLength = len(p.msgContent)
        elif f == 8:
            p.msgFormat = 0x08
            #TODO:可以在配置文件中增加对UCS2编码方码的配置,
            #实际可能是用UTF-16BE 或UTF-16LE
            p.msgContent = content.encode('UTF-16BE')#用utf-16 big-endian,
            p.msgLength = len(p.msgContent)
        elif f == 0:
            p.msgFormat = 0x00
            p.msgContent = content.encode('ascii')
            p.msgLength = len(p.msgContent)
        elif f == 3:
            p.msgFormat = 0x03
            p.msgContent = content
            p.msgLength = len(p.msgContent)
        elif f == 4:
            p.msgFormat = 0x04
            p.msgContent = content
            p.msgLength = len(p.msgContent)
        else:
            p.msgFormat = 0x00
            p.msgContent = content
            p.msgLength = len(p.msgContent)
        return p
    @staticmethod
    def makeSubmitResp(m):
        p = Smgp30SubmitResp()
        p.sequenceID = m.sequenceID
        return p
        
    @staticmethod
    def makeDeliver(content, f = 15):
        p = Smgp30Deliver()
        p.msgID = Smgp30Util.genMsgID()
        
        p.destTermID = '13715053570'
        #内容的编码是个问题,需要仔细处理
        #在msgFormat为0时,用ACSII,为4时,二进制,为8时,UCS,为15时GBK
        if f == 15:
            p.msgFormat = 0x15
            p.msgContent = content.encode('GB18030')
            p.msgLength = len(p.msgContent)
        elif f == 8:
            p.msgFormat = 0x08
            p.msgContent = content.encode('UTF-16BE')
            p.msgLength = len(p.msgContent)
        elif f == 0:
            p.msgFormat = 0x00
            p.msgContent = content.encode('ascii')
            p.msgLength = len(p.msgContent)
        elif f == 3:
            p.msgFormat = 0x03
            p.msgContent = content
            p.msgLength = len(p.msgContent)
        elif f == 4:
            p.msgFormat = 0x04
            p.msgContent = content
            p.msgLength = len(p.msgContent)
        else:
            p.msgFormat = 0x00
            p.msgContent = content.encode('ascii')
            p.msgLength = len(p.msgContent)
        return p
    @staticmethod
    def makeDeliverResp(m):
        p = Smgp30DeliverResp()
        p.sequenceID = m.sequenceID
        return p
        
    @staticmethod
    def makeActiveTest():
        p = Smgp30ActiveTest()
        return p
        
    @staticmethod
    def makeActiveTestResp(m):
        p = Smgp30ActiveTestResp()
        p.sequenceID = m.sequenceID
        return p
        
        
    @staticmethod
    def makeExit():
        p = Smgp30Exit()
        return p
    
    @staticmethod
    def makeExitResp(m):
        p = Smgp30ExitResp()
        p.sequenceID = m.sequenceID
        return p

        
class SmgpTLV(object):
    implements(IEncodable)
    def __init__(self):
        self.tag = ''
        self.length = ''
        self.value = ''
        
    def encode(self, strio, compDict = None):
        log.debug( repr(self.__class__) + 'encode')
        format = '!HH'
        strio.write(
            struct.pack(format, self.tag, self.length))
        if self.tag in [TP_pid, TP_udhi, ChargeUserType, ChargeTermType, 
                        DestTermType, PkTotal, PkNumber, SubmitMsgType,
                        SPDealReslt, SrcTermType, NodesCount, SrcType]:
            format = '!B'
        elif self.tag in [LinkID, ChargeTermPseudo, DestTermPseudo, 
                          SrcTermPseudo, MsgSrc, MServiceID]:
            format = '!' + str(self.length) + 's'
        strio.write(
            struct.pack(format, self.value))
        
    def decode(self, dataStr, length = 0):
        log.debug( repr(self.__class__) + 'decode')
        format = '!HH'
        self.tag, self.length = struct.unpack_from(format, dataStr, length)
        if self.tag in [TP_pid, TP_udhi, ChargeUserType, ChargeTermType, 
                        DestTermType, PkTotal, PkNumber, SubmitMsgType,
                        SPDealReslt, SrcTermType, NodesCount, SrcType]:
            format = '!B'
        elif self.tag in [LinkID, ChargeTermPseudo, DestTermPseudo, 
                          SrcTermPseudo, MsgSrc, MServiceID]:
            format = '!' + str(self.length) + 's'
        (self.value, ) = struct.unpack_from(format, dataStr, length + 4)

#    def toStr(self, strio = StringIO.StringIO()):
#        
#        self.encode(strio)
#        return strio.getvalue()
#
#    def fromStr(self, str):
#        #strio = StringIO.StringIO(str)
#        self.decode(str)
        
class SmgpHeader(object):
    implements(IEncodable)
    
    def __init__(self, packetLength = 12, requestID = ACTIVE_TEST, sequenceID = 1):
        self.packetLength = packetLength
        self.requestID = requestID
        self.sequenceID = sequenceID 
        
    def encode(self, strio, compDict = None):
        log.debug(repr(self.__class__) + 'encode')
        format = '!3I'
        strio.write(
            struct.pack(format, self.packetLength, self.requestID, self.sequenceID))
        
    def decode(self, dataStr, length = 0):
        log.debug(repr(self.__class__) + 'decode')
        format = '!3I'
        self.packetLength, self.requestID, self.sequenceID = struct.unpack_from(format, dataStr + length)

    def toStr(self):
        strio = StringIO.StringIO()
        self.encode(strio)
        return strio.getvalue()


    def fromStr(self, dataStr):
#        strio = StringIO.StringIO(str)
#        self.decode(strio)
        self.decode(str)
class Smgp30Header(SmgpHeader):
    pass

class Smgp30Login(Smgp30Header):
    def __init__(self, clientID = '', password = ''):
        Smgp30Header.__init__(self, LOGIN_LENGTH, LOGIN, SeqGen.nextID())
        self.clientID = ''
        self.authenticatorClient = ''
        self.loginMode = 0x02
        self.timestamp = 0
        self.version = 0x13
#        self.clientID = clientID
#        self.timestamp_str = time.strftime('%m%d%H%M%S', time.localtime())
#        self.timestamp = int(self.timestamp_str)
#        if password is not None:
#            m = md5.new()
#            authIO = StringIO.StringIO()
#            authIO.write(self.clientID)
#            for i in range(7):
#                authIO.write(chr(0))
#            authIO.write(password)
#            #self.timestamp = time.strftime('%m%d%H%M%S', time.localtime())
#            authIO.write(self.timestamp_str)
#            m.update(authIO.getvalue())
#            self.authenticatorClient = m.digest()
#        self.loginMode = 0x02
#        self.version = 0x13
        
#    def authentication(password):
#        m = md5.new()
#        authIO = StringIO.StringIO()
#        authIO.write(self.clientID)
#        for i in range(7):
#            authIO.write(chr(0))
#        authIO.write(password)
#        #self.timestamp = time.strftime('%m%d%H%M%S', time.localtime())
#        authIO.write(self.timestamp_str)
#        m.update(authIO.getvalue())
#        self.authenticatorClient = m.digest()
    
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!8s16sBIB'
        strio.write(struct.pack(format, self.clientID,
            self.authenticatorClient,
            self.loginMode,
            self.timestamp,
            self.version))
         
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!8s16sBIB' 
        self.clientID, self.authenticatorClient, self.loginMode, self.timestamp, self.version = struct.unpack_from(format, dataStr, length + 12)
        
class Smgp30LoginResp(Smgp30Header):
    def __init__(self, status = 0, sequenceID = 0):
        Smgp30Header.__init__(self, LOGIN_RESP_LENGTH, LOGIN_RESP, sequenceID)
        self.status = status
        self.authenticatorServer = ''
        self.version = 0x13
        
#    def authenticationServer(self, clientID, sharedSecret):
#        m = md5.new()
#        authIO = StringIO.StringIO()
#        authIO.write(str(self.status))
#        authIO.write(self.clientID)
#        authIO.write(sharedSecret)
#        m.update(authIO.getvalue())
#        self.authenticatorServer = m.digest()
        
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!I16sB'
        strio.write(struct.pack(format, self.status,
            self.authenticatorServer,
            self.version))
         
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!I16sB' 
        self.status, self.authenticatorServer, self.version = struct.unpack_from(format, dataStr, length +12)
        
        

class Smgp30Submit(Smgp30Header):
    def __init__(self):
        Smgp30Header.__init__(self, SUBMIT_LENGTH, SUBMIT, SeqGen.nextID())
        self.msgType = 2 #1 integer
        self.needReport = 1 #1 integer
        self.priority = 0 #1 integer
        self.serviceID = 'test' #10 Octet String
        self.feeType = '00' #2 Octet String
        self.feeCode = 'HELP' #6 Octet String
        self.msgFormat = 0x15 #1 integer
        self.validTime = '' #17 Octet String
        self.atTime = '' #17 Octet String
        self.srcTermID = '' #21 Octet String
        self.chargeTermID = '' #21 Octet String
        self.destTermIDCount = 1 #1 integer
        self.destTermID = '' #21* DestTerm Count Octet String        
        self.msgLength = 0 #1 integer
        self.msgContent = '' #<= 252 Octet String
        self.reserve = '' #8 Octet String
        
        self.tlvList = []
        
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!BBB10s2s6sB17s17s21s21sB'
        strio.write(struct.pack(format, self.msgType,
            self.needReport,
            self.priority,
            self.serviceID,
            self.feeType,
            self.feeCode,
            self.msgFormat,
            self.validTime,
            self.atTime,
            self.srcTermID,
            self.chargeTermID,
            self.destTermIDCount))
        temp1 = str(self.destTermIDCount * 21)
        temp2 = str(self.msgLength)
        format = '!' + temp1 + 'sB' + temp2 + 's8s'

        strio.write(struct.pack(format, self.destTermID, 
            self.msgLength,
            self.msgContent,
            self.reserve))
        
        for tlv in self.tlvList:
            tlv.encode(strio)
             
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!BBB10s2s6sB17s17s21s21sB' 
        (self.msgType,
            self.needReport,
            self.priority,
            self.serviceID,
            self.feeType,
            self.feeCode,
            self.msgFormat,
            self.validTime,
            self.atTime,
            self.srcTermID,
            self.chargeTermID,
            self.destTermIDCount) = struct.unpack_from(format, dataStr, length +12)
        s = struct.calcsize(format)
        format = '!' + str(self.destTermIDCount * 21) + 'sB'
        (self.destTermID, 
            self.msgLength) = struct.unpack_from(format, dataStr, length +12 + s)
        s2 = struct.calcsize(format)
        format = '!' + str(self.msgLength) + 's8s'
        (self.msgContent,
            self.reserve) = struct.unpack_from(format, dataStr, length +12 + s + s2)
        
        l = 12 + s + s2 + self.msgLength + 8
        self.tlvList = []
        while self.packetLength > l:
            tlv = SmgpTLV()
            tlv.decode(dataStr, l)
            self.tlvList.append(tlv)
            l += tlv.length + 4

class Smgp30SubmitResp(Smgp30Header):
    def __init__(self, sequenceID = 0):
        Smgp30Header.__init__(self, SUBMIT_RESP_LENGTH, SUBMIT_RESP, sequenceID)
        self.msgID = '' #10 string
        self.status = 0 #4 integer
  
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!10sI'
        strio.write(struct.pack(format, self.msgID,
            self.status))
         
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!10sI' 
        self.msgID, self.status = struct.unpack_from(format, dataStr, length +12)
        
class Smgp30Deliver(Smgp30Header):

    def __init__(self):
        Smgp30Header.__init__(self, DELIVER_LENGTH, DELIVER, SeqGen.nextID())
        self.msgID = '' #10 Octet String
        self.isReport = 0 #1 integer
        self.msgFormat = 15 #1 integer
        self.recvTime = '' #14 Octet String
        self.srcTermID = '' #21 Octet String
        self.destTermID = '' #21 Octet String
        self.msgLength = 0 #1 integer
        self.msgContent = '' #<=252 Octet String
        self.reserve = '' #8 Octet String
        
        self.tlvList = []
        
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!10sBB14s21s21sB'
        strio.write(struct.pack(format, self.msgID,
            self.isReport,
            self.msgFormat,
            self.recvTime,
            self.srcTermID,
            self.destTermID,
            self.msgLength))
        temp = str(self.msgLength)
        format = '!' + temp + 's8s'
        strio.write(struct.pack(format, self.msgContent,
            self.reserve))
             
        for tlv in self.tlvList:
            tlv.encode(strio)
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!10sBB14s21s21sB' 
        (self.msgID,
            self.isReport,
            self.msgFormat,
            self.recvTime,
            self.srcTermID,
            self.destTermID,
            self.msgLength) = struct.unpack_from(format, dataStr, length +12)
        s = struct.calcsize(format)
        format = '!' + str(self.msgLength) + 's8s'
        (self.msgContent,
            self.reserve) = struct.unpack_from(format, dataStr, length +12 + s)
        
        l = 12 + s + self.msgLength + 8
        self.tlvList = []
        while self.packetLength > l:
            tlv = SmgpTLV()
            tlv.decode(dataStr, l)
            self.tlvList.append(tlv)
            l += tlv.length + 4

class Smgp30DeliverResp(Smgp30Header):
    def __init__(self, sequenceID = 0):
        Smgp30Header.__init__(self, DELIVER_RESP_LENGTH, DELIVER_RESP, sequenceID)
        self.msgID = '' #10 string
        self.status = 0 #4 integer
  
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!10sI'
        strio.write(struct.pack(format, self.msgID,
            self.status))
         
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!10sI' 
        self.msgID, self.status = struct.unpack_from(format, dataStr, length +12)
       

class Smgp30ActiveTest(Smgp30Header):
    def __init__(self):
        Smgp30Header.__init__(self, ACTIVE_TEST_LENGTH, ACTIVE_TEST, SeqGen.nextID())

class Smgp30ActiveTestResp(Smgp30Header):
    def __init__(self, sequenceID = 0):
        Smgp30Header.__init__(self, ACTIVE_TEST_RESP_LENGTH, ACTIVE_TEST_RESP, sequenceID)

class Smgp30Exit(Smgp30Header):
    def __init__(self):
        Smgp30Header.__init__(self, EXIT_LENGTH, EXIT, SeqGen.nextID())

class Smgp30ExitResp(Smgp30Header):
    def __init__(self, sequenceID = 0):
        Smgp30Header.__init__(self, EXIT_RESP_LENGTH, EXIT_RESP, sequenceID)
    
class Smgp30Query(Smgp30Header):
    def __init__(self):
        Smgp30Header.__init__(self, QUERY_LENGTH, QUERY, SeqGen.nextID())
        self.time = '' #8
        self.query_type = 0x00 #1
        self.query_code = ''  #10
          
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!8sB10s'
        strio.write(struct.pack(format, self.time,
            self.query_type,
            self.query_code))
             
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!8sB10s' 
        (self.time,
            self.query_type,
            self.query_code) = struct.unpack_from(format, dataStr, length +12)
        
class Smgp30QueryResp(Smgp30Header):
    def __init__(self, sequenceID = 0):
        Smgp30Header.__init__(self, QUERY_RESP_LENGTH, QUERY_RESP, sequenceID)
        self.time = '' #8
        self.query_type = 0x00 #1
        self.query_code = ''  #10
        self.mt_tlmsg = 0 #4
        self.mt_tlusr = 0 #4
        self.mt_scs = 0 #4
        self.mt_wt = 0 #4
        self.mt_fl = 0 #4
        self.mo_scs = 0 #4
        self.mo_wt = 0 #4
        self.mo_fl = 0 #4
        self.reverse = '' #8
        
        
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!8sB10sIIIIIIII8s'
        strio.write(struct.pack(format, self.time,
            self.query_type, self.query_code,
            self.mt_tlmsg, self.mt_tlusr,
            self.mt_scs, self.mt_wt,
            self.mt_fl, self.mo_scs,
            self.mo_wt, self.mo_fl,
            self.reverse))
         
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!8sB10sIIIIIIII8s' 
        (self.time, self.query_type, self.query_code,
            self.mt_tlmsg, self.mt_tlusr,
            self.mt_scs, self.mt_wt,
            self.mt_fl, self.mo_scs,
            self.mo_wt, self.mo_fl,
            self.reverse) = struct.unpack_from(format, dataStr, length +12)
       
class Smgp30Forward(Smgp30Header):
    def __init__(self):
        Smgp30Header.__init__(self, FORWARD_LENGTH, FORWARD, SeqGen.nextID())
        self.msgID = '' #10
        self.destSMGWNo = '' #6
        self.srcSMGWNo = ''  #6
        self.smcNo = '' #6
        self.smType = 0x00 #1
        self.subType = 0x00 #1
        self.reportFlag = 0x00 #1
        self.priority = 0x00 #1
        self.serviceID = '' #10
        self.feeType = ''  #2
        self.feeCode = '' #6
        self.msgFormat = 0x00 #1
        self.validTime = '' #17
        self.atTime = '' #17 Octet String
        self.srcTermID = '' #21 Octet String
        self.destTermID = '' #21* DestTerm Count Octet String 
        self.chargeTermID = '' #21 Octet String  
        self.msgLength = 0x00 #1 integer
        self.msgContent = '' #<= 252 Octet String
        self.reserve = '' #8 Octet String
        
          
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!10s6s6s6sBBBB10s2s6sB17s17s21s21s21sB'
        strio.write(struct.pack(format, self.msgID,
            self.destSMGWNo,
            self.srcSMGWNo,
            self.smcNo,
            self.smType,
            self.subType,
            self.reportFlag,
            self.priority,
            self.serviceID,
            self.feeType,
            self.feeCode,
            self.msgFormat,
            self.validTime,
            self.atTime,
            self.srcTermID,
            self.destTermID,
            self.chargeTermID,
            self.msgLength))
        temp = str(self.msgLength)
        format = '!' + temp + 's8s'
        strio.write(struct.pack(format, self.msgContent, self.reserve))
             
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!10s6s6s6sBBBB10s2s6sB17s17s21s21s21sB' 
        (self.msgID,
            self.destSMGWNo,
            self.srcSMGWNo,
            self.smcNo,
            self.smType,
            self.subType,
            self.reportFlag,
            self.priority,
            self.serviceID,
            self.feeType,
            self.feeCode,
            self.msgFormat,
            self.validTime,
            self.atTime,
            self.srcTermID,
            self.destTermID,
            self.chargeTermID,
            self.msgLength) = struct.unpack_from(format, dataStr, length +12)
        s = struct.calcsize(format)
        format = '!' + str(self.msgLength) + 's8s'
        (self.msgContent,self.reserve) = struct.unpack_from(format, dataStr, length +12 + s)
        
class Smgp30ForwardResp(Smgp30Header):
    def __init__(self, sequenceID = 0):
        Smgp30Header.__init__(self, FORWARD_RESP_LENGTH, FORWARD_RESP, sequenceID)
        self.msgID = '' #10
        self.status = 0 #4
        
        
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!10sI'
        strio.write(struct.pack(format, self.msgID,
            self.status))
         
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!10sI' 
        (self.msgID,
            self.status) = struct.unpack_from(format, dataStr, length +12)
       
class Smgp30MtRouteUpdate(Smgp30Header):
    def __init__(self):
        Smgp30Header.__init__(self, MT_ROUTE_UPDATE_LENGTH, MT_ROUTE_UPDATE, SeqGen.nextID())
        self.updateType = 0x00 #1
        self.routeID = 0 #4
        self.srcGatewayID = ''  #6
        self.srcGatewayIP = ''  #15
        self.srcGatewayPort = 0x0000 #2
        self.startTermID = ''  #6
        self.endTermID = ''  #6
        self.areaCode = ''  #4
          
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!B4s6s15sH6s6s4s'
        strio.write(struct.pack(format, self.updateType,
            self.routeID,
            self.srcGatewayID,
            self.srcGatewayIP,
            self.srcGatewayPort,
            self.startTermID,
            self.endTermID,
            self.areaCode))
             
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!B4s6s15sH6s6s4s' 
        (self.updateType,
            self.routeID,
            self.srcGatewayID,
            self.srcGatewayIP,
            self.srcGatewayPort,
            self.startTermID,
            self.endTermID,
            self.areaCode) = struct.unpack_from(format, dataStr, length +12)
        
class Smgp30MtRouteUpdateResp(Smgp30Header):
    def __init__(self, sequenceID = 0):
        Smgp30Header.__init__(self, MT_ROUTE_UPDATE_RESP_LENGTH, MT_ROUTE_UPDATE_RESP, sequenceID)
        self.status = 0x00 #1
        
        
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!B'
        strio.write(struct.pack(format, self.status))
         
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!B' 
        (self.status, ) = struct.unpack_from(format, dataStr, length +12)
class Smgp30MoRouteUpdate(Smgp30Header):
    def __init__(self):
        Smgp30Header.__init__(self, MO_ROUTE_UPDATE_LENGTH, MO_ROUTE_UPDATE, SeqGen.nextID())
        self.updateType = 0x00 #1
        self.routeID = 0 #4
        self.srcGatewayID = ''  #6
        self.srcGatewayIP = ''  #15
        self.srcGatewayPort = 0x0000 #2
        self.srcTermID = ''  #21
          
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!B4s6s15sH21s'
        strio.write(struct.pack(format, self.updateType,
            self.routeID,
            self.srcGatewayID,
            self.srcGatewayIP,
            self.srcGatewayPort,
            self.srcTermID))
             
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!B4s6s15sH21s' 
        (self.updateType,
            self.routeID,
            self.srcGatewayID,
            self.srcGatewayIP,
            self.srcGatewayPort,
            self.srcTermID) = struct.unpack_from(format, dataStr, length +12)
        
class Smgp30MoRouteUpdateResp(Smgp30Header):
    def __init__(self, sequenceID = 0):
        Smgp30Header.__init__(self, MO_ROUTE_UPDATE_RESP_LENGTH, MO_ROUTE_UPDATE_RESP, sequenceID)
        self.status = 0x00 #1
        
        
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!B'
        strio.write(struct.pack(format, self.status))
         
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!B' 
        (self.status, ) = struct.unpack_from(format, dataStr, length +12)
    
class Smgp30PaymentRequest(Smgp30Header):
    def __init__(self):
        Smgp30Header.__init__(self, PAYMENT_REQUEST_LENGTH, PAYMENT_REQUEST, SeqGen.nextID())
        self.msgID = '' #20
        self.payMsgType = 0x0000 #2
        self.chargeTermID = ''  #21
        self.spCode = ''  #8
        self.srcTermID = '' #21
        self.destTermID = ''  #21
        self.serviceID = ''  #8
        self.feeType = '' #2
        self.feeCode = ''  #6
        self.fixedFee = ''  #6
        self.priority = 0x00  #1
        self.msgLength = 0x00  #1
        self.areaCode = ''  #4
        self.smgNo = ''  #6
        self.nxtNwkNd = ''  #6
        self.preNwkNd = ''  #6
        self.recvTime = ''  #14
        self.doneTime = ''  #14
        self.cdrType = 0x00  #1
        self.reserve = ''  #6
          
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!20sH21s8s21s21s8s2s6s6sBB4s6s6s6s14s14sB6s'
        strio.write(struct.pack(format, self.msgID,
        self.payMsgType,
        self.chargeTermID,
        self.spCode,
        self.srcTermID,
        self.destTermID,
        self.serviceID,
        self.feeType,
        self.feeCode,
        self.fixedFee,
        self.priority,
        self.msgLength,
        self.areaCode,
        self.smgNo,
        self.nxtNwkNd,
        self.preNwkNd,
        self.recvTime,
        self.doneTime,
        self.cdrType,
        self.reserve))
             
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!20sH21s8s21s21s8s2s6s6sBB4s6s6s6s14s14sB6s' 
        (self.msgID,
        self.payMsgType,
        self.chargeTermID,
        self.spCode,
        self.srcTermID,
        self.destTermID,
        self.serviceID,
        self.feeType,
        self.feeCode,
        self.fixedFee,
        self.priority,
        self.msgLength,
        self.areaCode,
        self.smgNo,
        self.nxtNwkNd,
        self.preNwkNd,
        self.recvTime,
        self.doneTime,
        self.cdrType,
        self.reserve) = struct.unpack_from(format, dataStr, length +12)
        
class Smgp30PaymentRequestResp(Smgp30Header):
    def __init__(self, sequenceID = 0):
        Smgp30Header.__init__(self, PAYMENT_REQUEST_RESP_LENGTH, PAYMENT_REQUEST_RESP, sequenceID)
        self.resultNotifyCode = 0x00 #1
        self.status = 0 #4
        
        
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!BI'
        strio.write(struct.pack(format, self.resultNotifyCode,self.status))
         
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!BI' 
        (self.resultNotifyCode,self.status) = struct.unpack_from(format, dataStr, length +12)
  
class Smgp30PaymentAffirm(Smgp30Header):
    def __init__(self):
        Smgp30Header.__init__(self, PAYMENT_AFFIRM_LENGTH, PAYMENT_AFFIRM, SeqGen.nextID())
        self.msgID = '' #20
        self.reportStatus = 0x00 #1
        self.feeAddr = ''  #21
        self.reserve = ''  #8
          
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!20sB21s8s'
        strio.write(struct.pack(format, self.msgID,
            self.reportStatus,
            self.feeAddr,
            self.reserve))
             
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!20sB21s8s' 
        (self.msgID,
            self.reportStatus,
            self.feeAddr,
            self.reserve) = struct.unpack_from(format, dataStr, length +12)
        
class Smgp30PaymentAffirmResp(Smgp30Header):
    def __init__(self, sequenceID = 0):
        Smgp30Header.__init__(self, PAYMENT_AFFIRM_RESP_LENGTH, PAYMENT_AFFIRM_RESP, sequenceID)
        self.status = 0 #4
        
        
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!I'
        strio.write(struct.pack(format, self.status))
         
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!I' 
        (self.status,) = struct.unpack_from(format, dataStr, length +12)
  
class Smgp30QueryUserState(Smgp30Header):
    def __init__(self):
        Smgp30Header.__init__(self, QUERY_USER_STATE_LENGTH, QUERY_USER_STATE, SeqGen.nextID())
        self.queryUserAddr = '' #21
        self.smgNo = '' #6
        self.reserve = ''  #8
          
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!21s6s8s'
        strio.write(struct.pack(format, self.queryUserAddr,
            self.smgNo,
            self.reserve))
             
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!21s6s8s' 
        (self.queryUserAddr,
            self.smgNo,
            self.reserve) = struct.unpack_from(format, dataStr, length +12)
        
class Smgp30QueryUserStateResp(Smgp30Header):
    def __init__(self, sequenceID = 0):
        Smgp30Header.__init__(self, QUERY_USER_STATE_RESP_LENGTH, QUERY_USER_STATE_RESP, sequenceID)
        self.userStatus = 0x00 #1
        self.count = 0 #4
        self.reserve = '' #8
        
        
    def encode(self, strio, compDict = None):
        Smgp30Header.encode(self, strio)
        format = '!BI8s'
        strio.write(struct.pack(format, self.status,
            self.count,self.reserve))
         
    def decode(self, dataStr, length = 0):
        Smgp30Header.decode(self, dataStr)
        format = '!BI8s' 
        (self.status,
            self.count,self.reserve) = struct.unpack_from(format, dataStr, length +12)
    
class Smgp30Report(object):
    def __init__(self):
        self.id = '' #10
        self.submit_date = '' #14
        self.done_date = '' #14
        self.stat = '' #7
        self.err = '' #3       
        
          
class Smgp30Protocol(Protocol):
    """This is Smgp30 Protocol!"""
    def __init__(self):
        self.header = Smgp30Header()
        self.buffer = ''
    
    def writeMessage(self, message):
        s = message.toStr()
        #log.debug(Utils.bin2hexstr(s))
        
        self.transport.write(s)
        
    
    
    def dataReceived(self, data):
        self.buffer += data
        
        while self.buffer:
            if len(self.buffer) >= 12:
                self.header.fromStr(self.buffer[:12])
                #self.buffer = self.buffer[2:]

            if len(self.buffer) >= self.header.packetLength:
                myChunk = self.buffer[:self.header.packetLength]
                print self.header.requestID
                if self.header.requestID == LOGIN:
                    m = Smgp30Login()
                elif self.header.requestID == LOGIN_RESP:
                    m = Smgp30LoginResp()
                elif self.header.requestID == SUBMIT:
                    m = Smgp30Submit()
                elif self.header.requestID == SUBMIT_RESP:
                    m = Smgp30SubmitResp()
                elif self.header.requestID == DELIVER:
                    m = Smgp30Deliver()
                elif self.header.requestID == DELIVER_RESP:
                    m = Smgp30DeliverResp()
                elif self.header.requestID == ACTIVE_TEST:
                    m = Smgp30ActiveTest()
                elif self.header.requestID == ACTIVE_TEST_RESP:
                    m = Smgp30ActiveTestResp()
                elif self.header.requestID == EXIT:
                    m = Smgp30Exit()
                elif self.header.requestID == EXIT_RESP:
                    m = Smgp30ExitResp()
                else:
                    import Utils
                    log.debug(Utils.bin2hexstr(myChunk))
                    raise SmgpParseError
                
                
                m.fromStr(myChunk)
                self.handler.recvMsg(m)
                
                self.buffer = self.buffer[self.header.packetLength:]
                self.header.packetLength = 12
            else:
                break
    

class Smgp30ClientProtocol(Smgp30Protocol):
    def connectionMade(self):
        """init a handler"""
        log.debug('Client connection made')
        self.handler = Smgp30ClientHandler(self)
        #self.factory.handlerList.append(self.handler)
        
        eventMgr.fire(Event(SMGP30CONNECTED, self), self)
        
    def connectionLost(self, reason):
        if reason.check(ConnectionDone):
            self.handler.closeConnection(True)
        else:
            log.debug(str(reason))
            self.handler.closeConnection(True)
            
        eventMgr.fire(Event(SMGP30CONNECTLOST, str(reason)), self)
        
class Smgp30ServerProtocol(Smgp30Protocol):
    def connectionMade(self):
        """init a handler"""
        log.debug('accept a connection')
        self.handler = Smgp30ServerHandler(self)
        
        eventMgr.fire(Event(SMGP30CONNECTED, self), self)
        
    def connectionLost(self, reason):
        if reason.check(ConnectionDone):
            self.handler.closeConnection(True)
        else:
            log.debug(str(reason))
            self.handler.closeConnection(True)
            
        eventMgr.fire(Event(SMGP30CONNECTLOST, str(reason)), self)
        
    def closeConnection(self):
        """主动关闭连接"""
        self.transport.lostConnection()
        
class Smgp30ClientFactory(ClientFactory):
    def __init__(self):
        self.protocol = Smgp30ClientProtocol
        #self.handlerList = []
        
    def startedConnecting(self, connector):
        eventMgr.fire(Event(SMGP30CONNECTING, connector), self)
        
        log.debug('started connectioning')
   
    def buildProtocol(self, addr):
        p = ClientFactory.buildProtocol(self,addr)
        eventMgr.fire(Event(SMGP30PROTOCOLBUILD, p), self)
        return p
    def clientConnectionFailed(self, connector, reason):
        """Called when a connection has failed to connect.

        It may be useful to call connector.connect() - this will reconnect.

        @type reason: L{twisted.python.failure.Failure}
        """
        eventMgr.fire(Event(SMGP30CONNECTFAIL, (connector, reason)), self)
        

    def clientConnectionLost(self, connector, reason):
        pass
        #eventMgr.fire(Event(SMGP30CONNECTLOST, p), self)
        
        
class Smgp30ServerFactory(ServerFactory):
    def __init__(self):
        self.protocol = Smgp30ServerProtocol
        #self.handlerList = []
        
    def startedConnecting(self, connector):
        eventMgr.fire(Event(SMGP30CONNECTING, connector), self)
        
        log.debug('started connectioning')
   
    def buildProtocol(self, addr):
        p = ServerFactory.buildProtocol(self,addr)
        eventMgr.fire(Event(SMGP30PROTOCOLBUILD, p), self)
        return p
        

class Smgp30ClientHandler(object):
    def __init__(self, p):
        self.p = p
        self.recvQueue = Queue.Queue(0)
        self.sendQueue = Queue.Queue(0)
        self.sendedDict = {}
        self.recvFlag = True
        self.sendFlag = True
        
        self.activeCaller = reactor.callLater(ACTIVE_SECOND, self.activeMessage)
        self.handleRecvThread = Thread(target = self.handleRecv)
        self.handleRecvThread.start()
        self.handleSendThread = Thread(target = self.handleSend)
        self.handleSendThread.start()
        
    def closeConnection(self, passive=False):
        """关闭连连:"""
        if passive:
            self.recvFlag = False
            self.sendFlag = False
            self.handleRecvThread.join()
            self.handleSendThread.join()
        else:
            self.recvFlag = False
            self.sendFlag = False
            self.handleRecvThread.join()
            self.handleSendThread.join()
            self.p.transport.loseConnection()
        
        
    def submitMessage(self, message):
        self.sendQueue.put(message)
        
    def sendMessage(self, message):
        caller, times = self.sendedDict.get(message.sequenceID, [None, 0])
        if caller == None:
            caller = reactor.callLater(RESEND_SECOND, self.resendMessage, message)
            self.sendedDict[message.sequenceID] = [caller, 1]
            self.p.writeMessage(message)
        else:
            caller = reactor.callLater(RESEND_SECOND, self.resendMessage, message)
            self.sendedDict[message.sequenceID] = [caller, times + 1]
            self.p.writeMessage(message)
            
    def resendMessage(self, message):
        caller, times = self.sendedDict.get(message.sequenceID, [None, 0])
        if times < 3:
            self.submitMessage(message)
        else:
            self.sendedDict.pop(message.sequenceID, None)
        
    def activeMessage(self):
        m = Smgp30Util.makeActiveTest()
        self.submitMessage(m)
        self.activeCaller = reactor.callLater(ACTIVE_SECOND, self.activeMessage)
        
    def handleResp(self, m):
        """收到RESP消息时，在已发字典中，停止取消重发定时器，删除已发消息"""
        caller, times = self.sendedDict.get(m.sequenceID, [None, 0])
        if caller != None:
            caller.cancel()
            self.sendedDict.pop(m.sequenceID, None)
                  
    def handleRecv(self):
        while self.recvFlag:
            try:
                try:
                    m = self.recvQueue.get(True, 2)
                except:
                    continue
                self.activeCaller.reset(ACTIVE_SECOND)
                log.debug('get recvQueue m:' + Utils.bin2hexstr(m.toStr()))
                if m.requestID == ACTIVE_TEST:
                    eventMgr.fire(Event(SMGP30ACTIVETEST_RECV, m), self)
                    resp = Smgp30Util.makeActiveTestResp(m)
                    self.submitMessage(resp)
                    log.debug('recv Test Message')
                    
                elif m.requestID == ACTIVE_TEST_RESP:
                    eventMgr.fire(Event(SMGP30ACTIVETESTRESP_RECV, m), self)
                    self.handleResp(m)
                    log.debug('recv Test Resp Message')
                
                elif m.requestID == DELIVER:
                    eventMgr.fire(Event(SMGP30DELIVER_RECV, m), self)
                    #作为服务器，收到Deliver消息时，先产生一个回应，再根据路由表转发给处理端，
                    resp = Smgp30Util.makeDeliverResp(m)
                    self.submitMessage(resp)
                    log.debug('recv Deliver Message')
                    
                    #路由到处理端
#                    r = routeTable.findRoute(m.srcTermID.strip('\x00'), m.destTermID.strip('\x00'), m.msgContent.strip('\x00'))
#                    if r != None:
#                        accounts.activeDict[r.id].submitMessage(m)
                    
                elif m.requestID == DELIVER_RESP:
                    eventMgr.fire(Event(SMGP30DELIVERRESP_RECV, m), self)
                    #作为服务器，收到Resp消息时，查已发消息字典，停止定时器重发，并删除相应的已发消息
                    self.handleResp(m)
                    log.debug('recv Deliver Resp Message')
                                      
                elif m.requestID == SUBMIT:
                    eventMgr.fire(Event(SMGP30SUBMIT_RECV, m), self)
                    #作为服务器，收到submit消息时，根据路由转发给处理端
                    resp = Smgp30Util.makeSubmitResp(m)
                    self.submitMessage(resp)
                    log.debug('recv Submit Message')
                    
                    #TODO:submit消息中destTermID可能包含多个号码，暂不支持多个号码的情况，后期再支持。
                    #路由到处理端
#                    r = routeTable.findRoute(m.srcTermID.strip('\x00'), m.destTermID.strip('\x00'), m.msgContent.strip('\x00'))
#                    if r != None:
#                        accounts.activeDict[r.id].submitMessage(m)
                    
                    
                elif m.requestID == SUBMIT_RESP:
                    eventMgr.fire(Event(SMGP30SUBMITRESP_RECV, m), self)
                    self.handleResp(m)
                    log.debug('recv Submit Resp Message')
                    
                elif m.requestID == LOGIN:
                    eventMgr.fire(Event(SMGP30LOGIN_RECV, m), self)
                    #收到登陆包后，验证验证用户，通过时在活动列表中添加，不通过时断开连接
                    
                    resp = Smgp30Util.makeLoginResp(m)
                    self.submitMessage(resp)
                    log.debug('recv Login Message')
                    
                elif m.requestID == LOGIN_RESP:
                    eventMgr.fire(Event(SMGP30LOGINRESP_RECV, m), self)
                    self.handleResp(m)
#                    caller, times = self.sendedDict.get(m.sequenceID, [None, 0])
#                    if caller != None:
#                        caller.cancel()
#                        self.sendedDict.pop(m.sequenceID, None)
                    log.debug('recv Login Resp Message')
                elif m.requestID == EXIT:
                    eventMgr.fire(Event(SMGP30EXIT_RECV, m), self)
                    #收到登陆包后，验证验证用户，通过时在活动列表中添加，不通过时断开连接
                    
                    resp = Smgp30Util.makeExitResp(m)
                    self.submitMessage(resp)
                    log.debug('recv Exit Message')
                    
                elif m.requestID == EXIT_RESP:
                    eventMgr.fire(Event(SMGP30EXITRESP_RECV, m), self)
                    self.handleResp(m)
#                    caller, times = self.sendedDict.get(m.sequenceID, [None, 0])
#                    if caller != None:
#                        caller.cancel()
#                        self.sendedDict.pop(m.sequenceID, None)
                    log.debug('recv Exit Resp Message')
                else:
                    pass
            except:                
                raise
                
    def handleSend(self):
        while self.sendFlag:
            try:
                try:
                    m = self.sendQueue.get(True, 2)
                except:
                    continue
                eventMgr.fire(Event(SMGP30SENDING, m), self)
                self.activeCaller.reset(ACTIVE_SECOND)
                log.debug('get sendQueue m:' + Utils.bin2hexstr(m.toStr()))
                if m.requestID == ACTIVE_TEST:
                    self.sendMessage(m)
                    eventMgr.fire(Event(SMGP30ACTIVETEST_SEND, m), self)
                    log.debug('send Test Message')
                elif m.requestID == ACTIVE_TEST_RESP:
                    self.p.writeMessage(m)
                    eventMgr.fire(Event(SMGP30ACTIVETESTRESP_SEND, m), self)
                    log.debug('send Test Resp Message')
                elif m.requestID == SUBMIT:
                    self.sendMessage(m)
                    eventMgr.fire(Event(SMGP30SUBMIT_SEND, m), self)
                    log.debug('send Submit Message')
                elif m.requestID == SUBMIT_RESP:
                    self.p.writeMessage(m)
                    eventMgr.fire(Event(SMGP30SUBMITRESP_SEND, m), self)
                    log.debug('send Submit Resp Message')
                elif m.requestID == DELIVER:
                    self.sendMessage(m)
                    eventMgr.fire(Event(SMGP30DELIVER_SEND, m), self)
                    log.debug('send Submit Message')
                elif m.requestID == DELIVER_RESP:
                    self.p.writeMessage(m)
                    eventMgr.fire(Event(SMGP30DELIVERRESP_SEND, m), self)
                    log.debug('send Submit Resp Message')
                elif m.requestID == LOGIN:
                    self.sendMessage(m)
                    eventMgr.fire(Event(SMGP30LOGIN_SEND, m), self)
                    log.debug('send Login Message')
                elif m.requestID == LOGIN_RESP:
                    self.p.writeMessage(m)
                    eventMgr.fire(Event(SMGP30LOGINRESP_SEND, m), self)
                    log.debug('send Login Resp Message')
                elif m.requestID == EXIT:
                    self.sendMessage(m)
                    eventMgr.fire(Event(SMGP30EXIT_SEND, m), self)
                    log.debug('send Login Message')
                elif m.requestID == EXIT_RESP:
                    self.p.writeMessage(m)
                    eventMgr.fire(Event(SMGP30EXITRESP_SEND, m), self)
                    log.debug('send Login Resp Message')
                    
                eventMgr.fire(Event(SMGP30SENDED, m), self)
                
            except:                
                raise
                
       
    def recvMsg(self, message):
        """
        TODO:
        """
        try:
            eventMgr.fire(Event(SMGP30RECEIVERED, message), self)
            try:
                self.recvQueue.put(message, 10)
            except:
                log.debug(str(sys.exc_info()+ str(message)))
        except:
            log.debug(str(sys.exc_info()))
         
class Smgp30ServerHandler(object):
    def __init__(self, p):
        self.p = p
        self.recvQueue = Queue.Queue(0)
        self.sendQueue = Queue.Queue(0)
        self.sendedDict = {}
        self.recvFlag = True
        self.sendFlag = True
        
        self.activeCaller = reactor.callLater(ACTIVE_SECOND, self.activeMessage)
        self.handleRecvThread = Thread(target = self.handleRecv)
        self.handleRecvThread.start()
        self.handleSendThread = Thread(target = self.handleSend)
        self.handleSendThread.start()
        
    def closeConnection(self, passive=False):
        """关闭连连:"""
        if passive:
            self.recvFlag = False
            self.sendFlag = False
            self.handleRecvThread.join()
            self.handleSendThread.join()
        else:
            self.recvFlag = False
            self.sendFlag = False
            self.handleRecvThread.join()
            self.handleSendThread.join()
            self.p.transport.loseConnection()
        
        
    def submitMessage(self, message):
        self.sendQueue.put(message)
        
    def sendMessage(self, message):
        caller, times = self.sendedDict.get(message.sequenceID, [None, 0])
        if caller == None:
            caller = reactor.callLater(RESEND_SECOND, self.resendMessage, message)
            self.sendedDict[message.sequenceID] = [caller, 1]
            self.p.writeMessage(message)
        else:
            caller = reactor.callLater(RESEND_SECOND, self.resendMessage, message)
            self.sendedDict[message.sequenceID] = [caller, times + 1]
            self.p.writeMessage(message)
            
    def resendMessage(self, message):
        caller, times = self.sendedDict.get(message.sequenceID, [None, 0])
        if times < 3:
            self.submitMessage(message)
        else:
            self.sendedDict.pop(message.sequenceID, None)
        
    def activeMessage(self):
        m = Smgp30Util.makeActiveTest()
        self.submitMessage(m)
        log.debug(Utils.bin2hexstr(m.toStr()))
        self.activeCaller = reactor.callLater(ACTIVE_SECOND, self.activeMessage)
        
    def handleResp(self, m):
        """收到RESP消息时，在已发字典中，停止取消重发定时器，删除已发消息"""
        caller, times = self.sendedDict.get(m.sequenceID, [None, 0])
        if caller != None:
            caller.cancel()
            self.sendedDict.pop(m.sequenceID, None)
                  
    def handleRecv(self):
        while self.recvFlag:
            try:
                try:
                    m = self.recvQueue.get(True, 2)
                except:
                    continue
                self.activeCaller.reset(ACTIVE_SECOND)
                log.debug('get recvQueue m:' + Utils.bin2hexstr(m.toStr()))
                if m.requestID == ACTIVE_TEST:
                    eventMgr.fire(Event(SMGP30ACTIVETEST_RECV, m), self)
                    resp = Smgp30Util.makeActiveTestResp(m)
                    self.submitMessage(resp)
                    log.debug('recv Test Message')
                    
                elif m.requestID == ACTIVE_TEST_RESP:
                    eventMgr.fire(Event(SMGP30ACTIVETESTRESP_RECV, m), self)
                    self.handleResp(m)
                    log.debug('recv Test Resp Message')
                
                elif m.requestID == DELIVER:
                    eventMgr.fire(Event(SMGP30DELIVER_RECV, m), self)
                    #作为服务器，收到Deliver消息时，先产生一个回应，再根据路由表转发给处理端，
                    resp = Smgp30Util.makeDeliverResp(m)
                    self.submitMessage(resp)
                    log.debug('recv Deliver Message')
                    
                    #路由到处理端
#                    r = routeTable.findRoute(m.srcTermID.strip('\x00'), m.destTermID.strip('\x00'), m.msgContent.strip('\x00'))
#                    if r != None:
#                        accounts.activeDict[r.id].submitMessage(m)
                    
                elif m.requestID == DELIVER_RESP:
                    eventMgr.fire(Event(SMGP30DELIVERRESP_RECV, m), self)
                    #作为服务器，收到Resp消息时，查已发消息字典，停止定时器重发，并删除相应的已发消息
                    self.handleResp(m)
                    log.debug('recv Deliver Resp Message')
                                      
                elif m.requestID == SUBMIT:
                    eventMgr.fire(Event(SMGP30SUBMIT_RECV, m), self)
                    #作为服务器，收到submit消息时，根据路由转发给处理端
                    resp = Smgp30Util.makeSubmitResp(m)
                    self.submitMessage(resp)
                    log.debug('recv Submit Message')
                    
                    #TODO:submit消息中destTermID可能包含多个号码，暂不支持多个号码的情况，后期再支持。
                    #路由到处理端
#                    r = routeTable.findRoute(m.srcTermID.strip('\x00'), m.destTermID.strip('\x00'), m.msgContent.strip('\x00'))
#                    if r != None:
#                        accounts.activeDict[r.id].submitMessage(m)
                    
                    
                elif m.requestID == SUBMIT_RESP:
                    eventMgr.fire(Event(SMGP30SUBMITRESP_RECV, m), self)
                    self.handleResp(m)
                    log.debug('recv Submit Resp Message')
                    
                elif m.requestID == LOGIN:
                    eventMgr.fire(Event(SMGP30LOGIN_RECV, m), self)
                    #收到登陆包后，验证验证用户，通过时在活动列表中添加，不通过时断开连接
                    
                    resp = Smgp30Util.makeLoginResp(m)
                    self.submitMessage(resp)
                    log.debug('recv Login Message')
                    
                elif m.requestID == LOGIN_RESP:
                    eventMgr.fire(Event(SMGP30LOGINRESP_RECV, m), self)
                    self.handleResp(m)
#                    caller, times = self.sendedDict.get(m.sequenceID, [None, 0])
#                    if caller != None:
#                        caller.cancel()
#                        self.sendedDict.pop(m.sequenceID, None)
                    log.debug('recv Login Resp Message')
                elif m.requestID == EXIT:
                    eventMgr.fire(Event(SMGP30EXIT_RECV, m), self)
                    #收到登陆包后，验证验证用户，通过时在活动列表中添加，不通过时断开连接
                    
                    resp = Smgp30Util.makeExitResp(m)
                    self.submitMessage(resp)
                    log.debug('recv Exit Message')
                    
                elif m.requestID == EXIT_RESP:
                    eventMgr.fire(Event(SMGP30EXITRESP_RECV, m), self)
                    self.handleResp(m)
#                    caller, times = self.sendedDict.get(m.sequenceID, [None, 0])
#                    if caller != None:
#                        caller.cancel()
#                        self.sendedDict.pop(m.sequenceID, None)
                    log.debug('recv Exit Resp Message')
                else:
                    pass
            except:
                raise
                
    def handleSend(self):
        while self.sendFlag:
            try:
                try:
                    m = self.sendQueue.get(True, 2)
                except:
                    continue
                eventMgr.fire(Event(SMGP30SENDING, m), self)
                self.activeCaller.reset(ACTIVE_SECOND)
                log.debug('get sendQueue m:' + Utils.bin2hexstr(m.toStr()))
                if m.requestID == ACTIVE_TEST:
                    log.debug(Utils.bin2hexstr(m.toStr()))
                    self.sendMessage(m)
                    eventMgr.fire(Event(SMGP30ACTIVETEST_SEND, m), self)
                    log.debug('send Test Message')
                elif m.requestID == ACTIVE_TEST_RESP:
                    self.p.writeMessage(m)
                    eventMgr.fire(Event(SMGP30ACTIVETESTRESP_SEND, m), self)
                    log.debug('send Test Resp Message')
                elif m.requestID == SUBMIT:
                    self.sendMessage(m)
                    eventMgr.fire(Event(SMGP30SUBMIT_SEND, m), self)
                    log.debug('send Submit Message')
                elif m.requestID == SUBMIT_RESP:
                    self.p.writeMessage(m)
                    eventMgr.fire(Event(SMGP30SUBMITRESP_SEND, m), self)
                    log.debug('send Submit Resp Message')
                elif m.requestID == DELIVER:
                    self.sendMessage(m)
                    eventMgr.fire(Event(SMGP30DELIVER_SEND, m), self)
                    log.debug('send Submit Message')
                elif m.requestID == DELIVER_RESP:
                    self.p.writeMessage(m)
                    eventMgr.fire(Event(SMGP30DELIVERRESP_SEND, m), self)
                    log.debug('send Submit Resp Message')
                elif m.requestID == LOGIN:
                    self.sendMessage(m)
                    eventMgr.fire(Event(SMGP30LOGIN_SEND, m), self)
                    log.debug('send Login Message')
                elif m.requestID == LOGIN_RESP:
                    self.p.writeMessage(m)
                    eventMgr.fire(Event(SMGP30LOGINRESP_SEND, m), self)
                    log.debug('send Login Resp Message')
                elif m.requestID == EXIT:
                    self.sendMessage(m)
                    eventMgr.fire(Event(SMGP30EXIT_SEND, m), self)
                    log.debug('send Login Message')
                elif m.requestID == EXIT_RESP:
                    self.p.writeMessage(m)
                    eventMgr.fire(Event(SMGP30EXITRESP_SEND, m), self)
                    log.debug('send Login Resp Message')
                    
                eventMgr.fire(Event(SMGP30SENDED, m), self)
                
            except:
                raise
                
       
    def recvMsg(self, message):
        """
        TODO:
        """
        try:
            eventMgr.fire(Event(SMGP30RECEIVERED, message), self)
            try:
                self.recvQueue.put(message, 10)
            except:
                log.debug(str(sys.exc_info()+ str(message)))
        except:
            log.debug(str(sys.exc_info()))
         